package com.zdb.n1.service.impl;

import com.zdb.n1.entity.FitnessGoal;
import com.zdb.n1.entity.User;
import com.zdb.n1.payload.response.MessageResponse;
import com.zdb.n1.repository.FitnessGoalRepository;
import com.zdb.n1.service.FitnessGoalService;
import com.zdb.n1.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Service
public class FitnessGoalServiceImpl implements FitnessGoalService {

    @Autowired
    private FitnessGoalRepository fitnessGoalRepository;

    @Autowired
    private UserService userService;

    @Override
    @Transactional
    public FitnessGoal saveFitnessGoal(FitnessGoal fitnessGoal) {
        User currentUser = userService.getCurrentUser();
        fitnessGoal.setUser(currentUser);
        
        if (fitnessGoal.getStartDate() == null) {
            fitnessGoal.setStartDate(LocalDateTime.now());
        }
        
        if (fitnessGoal.getProgress() == null) {
            fitnessGoal.setProgress(0.0);
        }
        
        return fitnessGoalRepository.save(fitnessGoal);
    }

    @Override
    public FitnessGoal getFitnessGoalById(Long id) {
        return fitnessGoalRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("未找到健身目标"));
    }

    @Override
    public List<FitnessGoal> getAllFitnessGoalsForCurrentUser() {
        User currentUser = userService.getCurrentUser();
        return fitnessGoalRepository.findByUserOrderByStartDateDesc(currentUser);
    }

    @Override
    public Page<FitnessGoal> getFitnessGoalsForCurrentUserPaged(Pageable pageable) {
        User currentUser = userService.getCurrentUser();
        return fitnessGoalRepository.findByUserOrderByStartDateDesc(currentUser, pageable);
    }

    @Override
    public List<FitnessGoal> getFitnessGoalsByStatus(FitnessGoal.GoalStatus status) {
        User currentUser = userService.getCurrentUser();
        return fitnessGoalRepository.findByUserAndStatusOrderByStartDateDesc(currentUser, status);
    }

    @Override
    public List<FitnessGoal> getFitnessGoalsByType(FitnessGoal.GoalType type) {
        User currentUser = userService.getCurrentUser();
        return fitnessGoalRepository.findByUserAndTypeOrderByStartDateDesc(currentUser, type);
    }

    @Override
    public List<FitnessGoal> getExpiredActiveGoals() {
        User currentUser = userService.getCurrentUser();
        return fitnessGoalRepository.findByUserAndTargetDateBeforeAndStatusOrderByStartDateDesc(
                currentUser, LocalDateTime.now(), FitnessGoal.GoalStatus.ACTIVE);
    }

    @Override
    public List<FitnessGoal> getUpcomingGoals() {
        User currentUser = userService.getCurrentUser();
        return fitnessGoalRepository.findByUserAndTargetDateAfterAndStatusOrderByTargetDateAsc(
                currentUser, LocalDateTime.now(), FitnessGoal.GoalStatus.ACTIVE);
    }

    @Override
    @Transactional
    public FitnessGoal updateGoalProgress(Long id, Double progress) {
        // 使用JPQL直接更新数据库记录，避免实体懒加载
        FitnessGoal goal = fitnessGoalRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("未找到健身目标"));
        
        // 获取所需的ID值，避免懒加载
        Long userId = null;
        try {
            userId = goal.getUser().getId();
        } catch (Exception e) {
            throw new RuntimeException("获取用户ID失败");
        }
        // 检查权限
        User currentUser = userService.getCurrentUser();
        // 设置状态
        goal.setProgress(progress);
        if (progress >= 100.0) {
            goal.setStatus(FitnessGoal.GoalStatus.COMPLETED);
            goal.setCompletedDate(LocalDateTime.now());
        }
        
        // 使用JdbcTemplate直接更新数据库
        fitnessGoalRepository.save(goal);
        
        // 重新获取数据，避免返回带有懒加载代理的实体
        return fitnessGoalRepository.findById(id)
                .map(updatedGoal -> {
                    FitnessGoal dto = new FitnessGoal();
                    dto.setId(updatedGoal.getId());
                    dto.setTitle(updatedGoal.getTitle());
                    dto.setDescription(updatedGoal.getDescription());
                    dto.setType(updatedGoal.getType());
                    dto.setTargetValue(updatedGoal.getTargetValue());
                    dto.setUnit(updatedGoal.getUnit());
                    dto.setStartDate(updatedGoal.getStartDate());
                    dto.setTargetDate(updatedGoal.getTargetDate());
                    dto.setCompletedDate(updatedGoal.getCompletedDate());
                    dto.setProgress(updatedGoal.getProgress());
                    dto.setStatus(updatedGoal.getStatus());
                    dto.setFrequency(updatedGoal.getFrequency());
                    dto.setFrequencyUnit(updatedGoal.getFrequencyUnit());
                    // 不设置user，避免懒加载问题
                    return dto;
                })
                .orElseThrow(() -> new RuntimeException("无法获取更新后的目标"));
    }

    @Override
    @Transactional
    public FitnessGoal completeGoal(Long id) {
        // 使用JPQL直接更新数据库记录，避免实体懒加载
        FitnessGoal goal = fitnessGoalRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("未找到健身目标"));
        
        // 获取所需的ID值，避免懒加载
        Long userId = null;
        try {
            userId = goal.getUser().getId();
        } catch (Exception e) {
            throw new RuntimeException("获取用户ID失败");
        }
        
        // 检查权限
        User currentUser = userService.getCurrentUser();
        if (!userId.equals(currentUser.getId())) {
            throw new RuntimeException("无权更新此目标");
        }
        
        // 设置状态
        goal.setStatus(FitnessGoal.GoalStatus.COMPLETED);
        goal.setCompletedDate(LocalDateTime.now());
        goal.setProgress(100.0);
        
        // 使用JdbcTemplate直接更新数据库
        fitnessGoalRepository.save(goal);
        
        // 重新获取数据，避免返回带有懒加载代理的实体
        return fitnessGoalRepository.findById(id)
                .map(updatedGoal -> {
                    FitnessGoal dto = new FitnessGoal();
                    dto.setId(updatedGoal.getId());
                    dto.setTitle(updatedGoal.getTitle());
                    dto.setDescription(updatedGoal.getDescription());
                    dto.setType(updatedGoal.getType());
                    dto.setTargetValue(updatedGoal.getTargetValue());
                    dto.setUnit(updatedGoal.getUnit());
                    dto.setStartDate(updatedGoal.getStartDate());
                    dto.setTargetDate(updatedGoal.getTargetDate());
                    dto.setCompletedDate(updatedGoal.getCompletedDate());
                    dto.setProgress(updatedGoal.getProgress());
                    dto.setStatus(updatedGoal.getStatus());
                    dto.setFrequency(updatedGoal.getFrequency());
                    dto.setFrequencyUnit(updatedGoal.getFrequencyUnit());
                    // 不设置user，避免懒加载问题
                    return dto;
                })
                .orElseThrow(() -> new RuntimeException("无法获取更新后的目标"));
    }

    @Override
    @Transactional
    public MessageResponse deleteFitnessGoal(Long id) {
        FitnessGoal goal = fitnessGoalRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("未找到健身目标"));
        
        User currentUser = userService.getCurrentUser();
        if (!goal.getUser().getId().equals(currentUser.getId())) {
            return MessageResponse.error("无权删除此目标");
        }
        
        fitnessGoalRepository.delete(goal);
        return MessageResponse.success("目标删除成功");
    }

    @Override
    public FitnessGoal getGoalById(Long id) {
        // 不验证用户权限，仅供管理员使用
        return fitnessGoalRepository.findById(id)
                .map(goal -> {
                    // 创建DTO，避免懒加载问题
                    FitnessGoal dto = new FitnessGoal();
                    dto.setId(goal.getId());
                    dto.setTitle(goal.getTitle());
                    dto.setDescription(goal.getDescription());
                    dto.setType(goal.getType());
                    dto.setTargetValue(goal.getTargetValue());
                    dto.setUnit(goal.getUnit());
                    dto.setStartDate(goal.getStartDate());
                    dto.setTargetDate(goal.getTargetDate());
                    dto.setCompletedDate(goal.getCompletedDate());
                    dto.setProgress(goal.getProgress());
                    dto.setStatus(goal.getStatus());
                    dto.setFrequency(goal.getFrequency());
                    dto.setFrequencyUnit(goal.getFrequencyUnit());
                    
                    // 设置用户ID而不是完整用户对象
                    User userRef = new User();
                    userRef.setId(goal.getUser().getId());
                    dto.setUser(userRef);
                    
                    return dto;
                })
                .orElseThrow(() -> new RuntimeException("未找到健身目标"));
    }

    @Override
    public List<FitnessGoal> getGoalsByUser(User user) {
        List<FitnessGoal> goals = fitnessGoalRepository.findByUserOrderByStartDateDesc(user);
        
        // 转换为没有懒加载关联的DTO
        return goals.stream().map(goal -> {
            FitnessGoal dto = new FitnessGoal();
            dto.setId(goal.getId());
            dto.setTitle(goal.getTitle());
            dto.setDescription(goal.getDescription());
            dto.setType(goal.getType());
            dto.setTargetValue(goal.getTargetValue());
            dto.setUnit(goal.getUnit());
            dto.setStartDate(goal.getStartDate());
            dto.setTargetDate(goal.getTargetDate());
            dto.setCompletedDate(goal.getCompletedDate());
            dto.setProgress(goal.getProgress());
            dto.setStatus(goal.getStatus());
            dto.setFrequency(goal.getFrequency());
            dto.setFrequencyUnit(goal.getFrequencyUnit());
            
            // 设置用户ID而不是完整用户对象
            User userRef = new User();
            userRef.setId(user.getId());
            dto.setUser(userRef);
            
            return dto;
        }).toList();
    }

    @Override
    public List<FitnessGoal> getGoalsByUserAndStatus(User user, FitnessGoal.GoalStatus status) {
        List<FitnessGoal> goals = fitnessGoalRepository.findByUserAndStatusOrderByStartDateDesc(user, status);
        
        // 转换为没有懒加载关联的DTO
        return goals.stream().map(goal -> {
            FitnessGoal dto = new FitnessGoal();
            dto.setId(goal.getId());
            dto.setTitle(goal.getTitle());
            dto.setDescription(goal.getDescription());
            dto.setType(goal.getType());
            dto.setTargetValue(goal.getTargetValue());
            dto.setUnit(goal.getUnit());
            dto.setStartDate(goal.getStartDate());
            dto.setTargetDate(goal.getTargetDate());
            dto.setCompletedDate(goal.getCompletedDate());
            dto.setProgress(goal.getProgress());
            dto.setStatus(goal.getStatus());
            dto.setFrequency(goal.getFrequency());
            dto.setFrequencyUnit(goal.getFrequencyUnit());
            
            // 设置用户ID而不是完整用户对象
            User userRef = new User();
            userRef.setId(user.getId());
            dto.setUser(userRef);
            
            return dto;
        }).toList();
    }

    @Override
    @Transactional
    public FitnessGoal updateGoal(Long id, FitnessGoal fitnessGoal) {
        // 验证目标是否存在
        FitnessGoal existingGoal = fitnessGoalRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("未找到健身目标"));
        
        // 保持ID不变
        fitnessGoal.setId(id);
        
        // 如果未设置进度，维持原有进度
        if (fitnessGoal.getProgress() == null) {
            fitnessGoal.setProgress(existingGoal.getProgress());
        }
        
        // 如果目标完成，设置完成日期
        if (fitnessGoal.getStatus() == FitnessGoal.GoalStatus.COMPLETED && existingGoal.getStatus() != FitnessGoal.GoalStatus.COMPLETED) {
            fitnessGoal.setCompletedDate(LocalDateTime.now());
            fitnessGoal.setProgress(100.0);
        }
        
        // 保存目标
        fitnessGoalRepository.save(fitnessGoal);
        
        // 重新获取数据，避免返回带有懒加载代理的实体
        return fitnessGoalRepository.findById(id)
                .map(updatedGoal -> {
                    FitnessGoal dto = new FitnessGoal();
                    dto.setId(updatedGoal.getId());
                    dto.setTitle(updatedGoal.getTitle());
                    dto.setDescription(updatedGoal.getDescription());
                    dto.setType(updatedGoal.getType());
                    dto.setTargetValue(updatedGoal.getTargetValue());
                    dto.setUnit(updatedGoal.getUnit());
                    dto.setStartDate(updatedGoal.getStartDate());
                    dto.setTargetDate(updatedGoal.getTargetDate());
                    dto.setCompletedDate(updatedGoal.getCompletedDate());
                    dto.setProgress(updatedGoal.getProgress());
                    dto.setStatus(updatedGoal.getStatus());
                    dto.setFrequency(updatedGoal.getFrequency());
                    dto.setFrequencyUnit(updatedGoal.getFrequencyUnit());
                    
                    // 设置用户ID而不是完整用户对象
                    User userRef = new User();
                    userRef.setId(updatedGoal.getUser().getId());
                    dto.setUser(userRef);
                    
                    return dto;
                })
                .orElseThrow(() -> new RuntimeException("无法获取更新后的目标"));
    }

    @Override
    @Transactional
    public MessageResponse deleteGoal(Long id) {
        // 不验证用户权限，仅供管理员使用
        FitnessGoal goal = fitnessGoalRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("未找到健身目标"));
        
        fitnessGoalRepository.delete(goal);
        return MessageResponse.success("目标删除成功");
    }
} 